import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import org.jdom.*;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

/**
 * 
 * Watches one or several directories. If the structure of one of the directories under watch changes, 
 * it will notify.
 *
 */
public class DirectoryWatcher {
	private Vector<File> mDirectories;
	private File mXMLFile;
	
	public DirectoryWatcher(File xmlFile) {
		mDirectories = new Vector<File>();
		mXMLFile = xmlFile;
		//read in saved settings from XML
		
		Document doc = new Document(new Element("rootElement"));
		doc.getRootElement().addContent(
				new Element("Directory").setAttribute(
						"path", "..\\directoriesWatched.xml"));
		Element e = doc.getRootElement().getChild("Directory");
		
	}
	
	/**
	 * 
	 * @param dirToAdd
	 * @return returns true if dir was added successfully, returns false otherwise.
	 */
	public boolean addDirectory(File dirToAdd) {
		assert dirToAdd != null : "dirToAdd was null";
		assert dirToAdd.isDirectory() == true : "dirToAdd was not a directory";
		return false;
	}
	
	/**
	 * 
	 * @param dirToRemove
	 * @return returns true if dir was removed, returns false otherwise.
	 */
	public boolean removeDirectory(File dirToRemove) {
		assert dirToRemove != null : "dirToRemove was null";
		assert dirToRemove.isDirectory() == true : "dirToAdd was not a directory";
		return false;
	}
	
	/**
	 * 
	 * @return Returns true if one of the watched directories has changed in its structure since last time, false otherwise.
	 */
	public boolean directoriesHasChanged() {
		return false;
	}
	
	/**
	 * 
	 * @return A Vector of files which had been changed (i.e. added or removed) since last time.
	 */
	public Vector<File> getChangedFiles() {
		Vector<File> fileVector = new Vector<File>(20);
		//check for which files were changed since last time
		//read changed files into vector
		return fileVector;
	}
	
	/**
	 * 
	 * @return True if there was an xml-file to read, false otherwise
	 */
	public boolean readSavedDirectories() throws JDOMException {
		assert mXMLFile != null : "the XML file was null";
		System.out.println("Loading XML data from " + mXMLFile.getName() + "... ");
		if(mXMLFile.exists()) {
			SAXBuilder builder = new SAXBuilder();
			try {
				Document doc = builder.build(mXMLFile);
				List<Element> elements = doc.getContent();
				Element dirElement = null;
				
				for(int i = 0; i < elements.size(); i++) { //grabbing the element which contains directories as sub-elements
					if(elements.get(i).getName().equalsIgnoreCase("directoriesWatched")) {
						dirElement = elements.get(i);
					}
				}
				
				if(dirElement == null) { //throw an exception if the element was not found.
					JDOMException e = new JDOMException("Could not find element 'directoriesWatched' in XML tree.\nIs it spelled wrong or is non-existant?");
					throw e;
				}
				else {
					//TODO:extract paths from XML-elements to make Files. Then push files onto mDirectories.
				}
				
				
				
			} catch (Exception e) {
				System.err.println("Exception: Could not read/parse from XML File.\nReason: " + e.getMessage());
			} 
			
			
			
			System.out.println("done");
			return true;
		}
		else
			System.out.println("failed");
			return false;
		
	}
	
	public void saveDirectories() {
		assert mXMLFile != null : "the XMl file was null";
		if(mXMLFile.exists()) {
			XMLOutputter outputter = new XMLOutputter();
			Document doc = generateXMLDocument();
			
			try {
				outputter.output(doc, new FileOutputStream(mXMLFile));
			} catch (Exception e) {
				System.err.println("Exception: Could not output to XML File.\nReason: " + e.getMessage());
			}
		}	
	}
	
	private org.jdom.Document generateXMLDocument() {
		Document doc = new Document();
		
		Element root = new Element("cppbuilder");
		Element directoriesWatched = new Element("directoriesWatched");
		for(File f : mDirectories) {
			if(f.isDirectory()) {
				Element aDir = new Element(f.getName());
				aDir.setAttribute("path", f.getAbsolutePath());
				directoriesWatched.addContent(aDir);
			}
		}
		root.addContent(directoriesWatched);
		doc.addContent(root);
		
		return doc;
	}
	
	public static void main(String[] args) {
		//tester for DirectoryWatcher
		DirectoryWatcher dw = new DirectoryWatcher(new File(
				"I:\\Documents and Settings\\ivar\\Desktop\\cppbuilder\\directoriesWatched.xml"));
	}

}
